home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1998 #4
/
Amiga Plus CD - 1998 - No. 4.iso
/
pd
/
tools
/
wbstars2.0
/
source
/
cback.a
next >
Wrap
Text File
|
1997-05-25
|
14KB
|
536 lines
*
* C initial startup procedure under AmigaDOS
*
INCLUDE "exec/types.i"
INCLUDE "exec/alerts.i"
INCLUDE "exec/nodes.i"
INCLUDE "exec/lists.i"
INCLUDE "exec/ports.i"
INCLUDE "exec/libraries.i"
INCLUDE "exec/tasks.i"
INCLUDE "exec/memory.i"
INCLUDE "exec/execbase.i"
INCLUDE "libraries/dos.i"
INCLUDE "libraries/dosextens.i"
FUNCDEF MACRO * function
_LVO\1 EQU FUNC_CNT
FUNC_CNT SET FUNC_CNT-6
ENDM
FUNC_CNT SET LIB_NONSTD
INCLUDE "exec/exec_lib.i"
INCLUDE "libraries/dos_lib.i"
INCLUDE "workbench/startup.i"
AbsExecBase EQU 4
TINY EQU 0
callsys macro
CALLLIB _LVO\1
endm
xdef XCEXIT ; exit(code) is standard way to leave C.
xdef @XCEXIT
xref LinkerDB ; linker defined base value
xref _BSSBAS ; linker defined base of BSS
xref _BSSLEN ; linker defined length of BSS
xref _main ; Name of C program to start with.
xref __fpinit * initialize floating point
xref __fpterm * terminate floating point
* library references
csect _NOMERGE,0,0,0,4
xref MemCleanup
xref FindTask
start:
movem.l d1-d6/a0-a6,-(a7)
REGSIZE EQU (6+7)*4
lea REGSIZE(a7),A5 * determine old stack pointer
move.l a0,a2 * save command pointer
move.l d0,d2 * and command length
lea LinkerDB,a4 * load base register
move.l AbsExecBase.W,a6
move.l a6,SysBase(A4)
move.l a7,_StackPtr(A4) * Save stack ptr
clr.l WBenchMsg(A4)
*------ Clear out our BSS section
lea _BSSBAS,a3 * get base of BSS
moveq #0,d1
move.l #_BSSLEN,d0 * get length of BSS in longwords
bra.s clr_lp * and clear for length given
clr_bss move.l d1,(a3)+
clr_lp dbf d0,clr_bss
*------ get the address of our task
move.l ThisTask(a6),A3
*----- clear any pending signals
moveq #0,d0
move.l #$00003000,d1
callsys SetSignal
*------ are we running as a son of Workbench?
move.l pr_CurrentDir(A3),curdir(A4)
tst.l pr_CLI(A3)
beq fromWorkbench
*=======================================================================
*====== CLI Startup Code ===============================================
*=======================================================================
fromCLI:
*------ attempt to open DOS library:
bsr.w openDOS
*------ Duplicate the current directory for the called process
move.l curdir(A4),D1
move.l DOSBase(A4),A6
callsys DupLock
move.l D0,curdir(A4)
*------ find command name:
move.l pr_CLI(A3),a0
add.l a0,a0 ; bcpl pointer conversion
add.l a0,a0
move.l cli_CommandName(a0),a1
add.l a1,a1 ; bcpl pointer conversion
add.l a1,a1
*------ collect parameters:
move.l d2,d0 ; get command line length
moveq.l #0,d1
move.b (a1)+,d1
move.l A1,D4 ;save our pointer
move.l d1,d3
add.l d1,d1 ; double length since we copy it twice
add.l d1,d0 ; add length of command name
addq.l #5,d0 ; allow for space after command
addq.l #4,d0 ; As well as for the roundup
* ; changed from 5 to 9 for quotes
*
*------ We have the length of the command string to be copied.
*------ Allocate space for it.
*------ Round up to the nearest 4 bytes
lsl.l #2,d0
add.l memsize(A4),d0
move.l d0,memsize(A4)
************************************************************************
************************************************************************
******** Allocate and copy over the code to do the magic stuff *********
************************************************************************
************************************************************************
lea memlist(A4),A0
move.l AbsExecBase.W,a6
callsys AllocEntry ;get a place to put the code
* btst.l #31,d0 ;did we get the memory we asked for?
* beq cliexit ;no, can't do anything then
move.l D0,A1
move.l D0,-(A7) ;remember the chunk we allocated
*------ Now we copy the code over
movea.l ML_SIZE+ME_ADDR(A1),A1 ;locate our allocated block
*------ Copy over the command line to the allocated area
lea commandbuf-copybeg(A1),A3
*------ At this point, we have:
* A0 - Work pointer
* A1 - Pointer to Allocated memory block
* A2 - Pointer to program name
* A3 - Pointer to target buffer
* A3 - Pointer to our process structure
* D0 - Work register
* D1 - Work register
* D2 - length of command name
* D3 - length of program name
* D4 - Pointer to program name
movea.l D4,A0 ; Load program name
move.l D3,D0 ; and length
move.b #'"',(a3)+
bra.s cpy1
cpycmd: move.b (A0)+,(A3)+ ; copy over the command name
cpy1: dbf d0,cpycmd
move.b #'"',(a3)+
move.b #' ',(A3)+ ; add the space delimiter
move.l A2,A0 ; Load command text
move.l D2,D0 ; and length
bra.s cpy2
cpylin: move.b (A0)+,(A3)+
cpy2: dbf d0,cpylin
clr.b (A3)+
*------ Now copy over the program name
move.l A3,_ProgramName(A4)
move.l D4,A0
move.l D3,D0
bra.s cpy3
cpypgm: move.b (A0)+,(A3)+
cpy3: dbf D0,cpypgm
clr.b (A3) ;don't forget trailing null on name
*------ First we want to put it into our seglist
lea segexit-copybeg(A1),A2
move.l A2,XCEXIT+2(A4) ;patch the jump instruction
lea start-4(PC),A2
* Now we have: A1 to our new fake segment
* A2 to the start of the real seglist
move.l #(copyend-copybeg)/4,(A1)+
move.l A1,D3
lsr.l #2,D3 ;convert it to a bptr to the list
move.l (A2),(A1)+ ;save our next segment pointer
clr.l (A2) ;and kill it from the chain
*------ We have the seglist
lea AutoLoader(PC),A2
move.l #(copyend-AutoLoader)-1,D0
copyit move.b (A2)+,(A1)+
dbf d0,copyit
*------ See if they want to do some I/O
tst.l _BackGroundIO(A4)
beq noio
lea current_window(A4),A0
move.l A0,D1
move.l #1005,D2
move.l DOSBase(A4),A6
callsys Open
move.l d0,_Backstdout(A4)
noio:
move.l AbsExecBase.w,A6
*------ If under 2.0 Flush cache
moveq #24,d0
cmp.w $14(a6),d0
bcs.b nocache
moveq #-1,d0
callsys CacheClearU
nocache:
callsys Forbid
*------ Attach the task to do the dirty work
move.l _procname(A4),D1 ; Name of task to start
move.l _priority(A4),D2 ; Priority of background task
move.l _stack(A4),D4 ; Stack size of created task
move.l DOSBase(A4),A6
callsys CreateProc
move.l A6,A3 ; restore dosbase to close it
tst.l D0
bne ok
*------ Serious problems. For some reason the CreateProc failed.
*------ We need to free the AlocEntry memory and go home
move.l (A7)+,A2
movea.l ML_SIZE+ME_ADDR(A2),A1 ;locate our allocated block
*------ Also must get rid of current directory
move.l curdir(A4),D1
callsys UnLock
move.l A2,A0
move.l AbsExecBase.w,A6
callsys FreeEntry
move.l #104,D0
bra cliexit
ok:
*------ The task started ok, attach the memory we allocated to
*------ its task control block
move.l D0,A2
move.l (a7)+,A1 ;locate the memory we allocated
lea -pr_MsgPort(A2),A2
lea TC_MEMENTRY(A2),A0
* ADDTAIL
LEA LH_TAIL(A0),A0
MOVE.L LN_PRED(A0),D0
MOVE.L A1,LN_PRED(A0)
MOVE.L A0,(A1)
MOVE.L D0,LN_PRED(A1)
MOVE.L D0,A0
MOVE.L A1,(A0)
move.l #0,D0
cliexit:
move.l AbsExecBase.w,A6
callsys Permit
move.l A3,A1
move.l AbsExecBase.w,A6
callsys CloseLibrary
movem.l (a7)+,d1-d6/a0-a6
rts
*=======================================================================
*====== Workbench Startup Code =========================================
*=======================================================================
fromWorkbench:
move.l TC_SPLOWER(A3),_base(A4) ; set base of stack
add.l #128,_base(A4) ;allow for parms overflow
*------ open the DOS library:
bsr.w openDOS
lea xcexit(PC),A2
move.l A2,XCEXIT+2(A4) ;patch the jump instruction
*------ we are now set up. wait for a message from our starter
bsr.w waitmsg
move.l d0,WBenchMsg(A4)
move.l d0,-(SP)
*
move.l d0,a2 ; get first argument
move.l sm_ArgList(a2),d0
beq.s do_cons
move.l DOSBase(A4),a6
move.l d0,a0
move.l wa_Lock(a0),d1
callsys DupLock
move.l d0,curdir(A4)
move.l d0,d1
callsys CurrentDir
do_cons:
move.l sm_ToolWindow(a2),d1 ; get the window argument
beq.s do_main
move.l #MODE_OLDFILE,d2
callsys Open
move.l d0,stdin(A4)
beq.s do_main
lsl.l #2,d0
move.l d0,a0
move.l fh_Type(a0),pr_ConsoleTask(A3)
do_main:
move.l WBenchMsg(A4),a0 ; get address of workbench message
move.l a0,-(a7) ; push argv
pea NULL(A4) ; push argc
move.l sm_ArgList(a0),a0 ; get address of arguments
move.l wa_Name(a0),_ProgramName(A4) ; get name of program
*------ For startup from workbench, there is no reason to go through
*------ The fancy stuff to make the startup work. Just run the
*------ Code directly
jsr __fpinit(PC)
jsr _main
moveq.l #0,d0
bra.w exit2
************************************************************************
************************************************************************
************* *************
************* Start of code that is copied to fake segment *************
************* *************
************************************************************************
************************************************************************
copybeg:
DC.L (copyend-copybeg)/4
next: DC.L 0
AutoLoader:
move.l a7,d0
movem.l d1-d6/a0-a6,-(a7)
move.l d0,a5
move.l AbsExecBase.w,a6
lea LinkerDB,A4 ; load base register
move.l a7,_StackPtr(A4)
bsr.w openDOS
suba.l a1,a1
suba.l a1,a1
callsys FindTask
move.l d0,A3
move.l TC_SPLOWER(A3),_base(A4) ; set base of stack
add.l #128,_base(A4) ;allow for parms overflow
move.l pr_SegList(A3),a0 ;locate the segment list
add.l A0,A0
add.l A0,A0 ;and convert to an APTR
move.l 12(A0),A1 ;so we can access the segments
add.l A1,A1
add.l A1,A1
move.l (A1),seglist(A4) ;save the remainder for later
move.l (A1),12(A0) ;cut off our segment
move.l curdir(A4),D1
move.l DOSBase(A4),a6
callsys CurrentDir
pea commandbuf(PC)
jsr __fpinit
jsr _main ; call C entrypoint
addq #4,A7
*------ Unlock the directory we set up for them
segexit:
move.l DOSBase(A4),a6
move.l curdir(A4),D1
callsys UnLock
moveq.l #0,d0 ; set successful status
xcexit:
exit2:
IFEQ TINY
move.l _ONEXIT(A4),d0 ; exit trap function?
beq.s exit3
move.l d0,a0
jsr (a0)
ENDC
exit3 jsr MemCleanup ; cleanup leftover memory alloc.
jsr __fpterm
done_1c:
*------ if we ran from CLI, skip workbench cleanup:
tst.l WBenchMsg(A4)
beq.s exitToDOS
move.l DOSBase(A4),a6
move.l stdin(A4),d1
beq.s done_4
callsys Close
done_4:
*------ return the startup message to our parent
* we forbid so workbench can't UnLoadSeg() us
* before we are done:
move.l curdir(a4),d1
beq.s done_5
callsys UnLock
done_5:
move.l AbsExecBase.w,A6
callsys Forbid
move.l WBenchMsg(A4),a1
callsys ReplyMsg
*------ this rts sends us back to DOS:
exitToDOS:
movea.l _StackPtr(a4),a3 ; Put old stack pointer somewhere safe.
*------ They are done so unload them
move.l seglist(A4),D1
move.l DOSBase(A4),a6
callsys UnLoadSeg
move.l a6,a1
move.l AbsExecBase.w,a6
callsys CloseLibrary ; close Dos library
movea.l a3,SP ; restore stack ptr
movem.l (a7)+,d1-d6/a0-a6
rts
*-----------------------------------------------------------------------
* Open the DOS library:
openDOS
lea DOSName(A4),A1
moveq.l #0,D0
callsys OpenLibrary
move.l D0,DOSBase(A4)
beq noDOS
rts
*-----------------------------------------------------------------------
noDOS:
moveq.l #100,d0
bra exit2
copyend:
commandbuf:
************************************************************************
************************************************************************
************** **************
************** End of code that is copied to fake segment **************
************** **************
************************************************************************
************************************************************************
*-----------------------------------------------------------------------
* This routine gets the message that workbench will send to us
* called with task id in A3
waitmsg:
lea pr_MsgPort(A3),a0 ; our process base
callsys WaitPort
lea pr_MsgPort(A3),a0 ; our process base
callsys GetMsg
rts
csect __MERGED,1,0,0,4
*------ These externals control the task that is started
xref _BackGroundIO ; flag to indicate background task
* ; wants to do I/O
xref _stack ; stack space for created task
xref _procname ; name of process to be created
xref _priority ; priority to create process at
xref DOSBase
xref MathBase
xref MathTransBase
*
xdef NULL,SysBase,WBenchMsg
xdef curdir,_mbase,_mnext,_msize,_tsize
xdef _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
xdef _SIGINT,_Backstdout
xdef _ProgramName,_StackPtr,_base
*
* cnop 0,4
memlist ds.b LN_SIZE
dc.w 1
dc.l MEMF_PUBLIC
memsize dc.l copyend-copybeg
XCEXIT
@XCEXIT dc.w $4ef9
dc.l 0
seglist dc.l 0
NULL dc.l 0 ;
_base dc.l 0 ; base of stack
_mbase dc.l 0 ; base of memory pool
_mnext dc.l 0 ; next available memory location
_msize dc.l 0 ; size of memory pool
_tsize dc.l 0 ; total size?
_oserr equ *
_OSERR dc.l 0
_FPERR dc.l 0
_SIGFPE dc.l 0
_SIGINT dc.l 0
_ONERR dc.l 0
_ONEXIT dc.l 0
_ONBREAK dc.l 0
curdir dc.l 0
SysBase dc.l 0
WBenchMsg dc.l 0
_StackPtr dc.l 0
dosCmdLen dc.l 0
dosCmdBuf dc.l 0
stdin dc.l 0
_Backstdout dc.l 0 ;filehandle for I/O
_ProgramName dc.l 0
DOSName dc.b 'dos.library',0
current_window dc.b '*',0
END